home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / checkbox / registries / udev.py < prev    next >
Text File  |  2009-11-05  |  18KB  |  529 lines

  1. #
  2. # This file is part of Checkbox.
  3. #
  4. # Copyright 2008 Canonical Ltd.
  5. #
  6. # Checkbox is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # Checkbox is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with Checkbox.  If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. import os
  20. import re
  21. import string
  22. import posixpath
  23.  
  24. from curses.ascii import isprint
  25.  
  26. from checkbox.lib.bit import get_bitmask, test_bit
  27. from checkbox.lib.cache import cache
  28. from checkbox.lib.dmi import Dmi, DmiNotAvailable
  29. from checkbox.lib.input import Input
  30. from checkbox.lib.pci import Pci
  31. from checkbox.lib.usb import Usb
  32.  
  33. from checkbox.properties import String
  34. from checkbox.registry import Registry
  35. from checkbox.registries.command import CommandRegistry
  36. from checkbox.registries.link import LinkRegistry
  37. from checkbox.registries.map import MapRegistry
  38.  
  39.  
  40. class DeviceRegistry(Registry):
  41.  
  42.     def __init__(self, environment, attributes):
  43.         super(DeviceRegistry, self).__init__()
  44.         self._environment = environment
  45.         self._attributes = attributes
  46.  
  47.     def __str__(self):
  48.         strings = ["%s: %s" % (k, v) for k, v in self.items()
  49.             if not isinstance(v, Registry)]
  50.  
  51.         return "\n".join(strings)
  52.  
  53.     def _get_bus(self):
  54.         sys_path = posixpath.join("/sys%s" % self._environment["DEVPATH"], "subsystem")
  55.         if posixpath.islink(sys_path):
  56.             link = os.readlink(sys_path)
  57.             if "/" in link:
  58.                 return posixpath.basename(link)
  59.  
  60.         return None
  61.  
  62.     def _get_category(self):
  63.         if "sys_vendor" in self._attributes:
  64.             return "SYSTEM"
  65.  
  66.         if "IFINDEX" in self._environment:
  67.             return "NETWORK"
  68.  
  69.         if "PCI_CLASS" in self._environment:
  70.             pci_class = self._environment["PCI_CLASS"]
  71.             if len(pci_class) > 4:
  72.                 pci_class = pci_class[:-2]
  73.  
  74.             subclass_id = int(pci_class[-2:], 16)
  75.             class_id = int(pci_class[:-2], 16)
  76.  
  77.             if class_id == Pci.BASE_CLASS_NETWORK:
  78.                 return "NETWORK"
  79.  
  80.             if class_id == Pci.BASE_CLASS_DISPLAY:
  81.                 return "VIDEO"
  82.  
  83.             if class_id == Pci.BASE_CLASS_SERIAL \
  84.                and subclass_id == Pci.CLASS_SERIAL_USB:
  85.                 return "USB"
  86.  
  87.             if class_id == Pci.BASE_CLASS_STORAGE:
  88.                 if subclass_id == Pci.CLASS_STORAGE_SCSI:
  89.                     return "SCSI"
  90.  
  91.                 if subclass_id == Pci.CLASS_STORAGE_IDE:
  92.                     return "IDE"
  93.  
  94.                 if subclass_id == Pci.CLASS_STORAGE_FLOPPY:
  95.                     return "FLOPPY"
  96.  
  97.                 if subclass_id == Pci.CLASS_STORAGE_RAID:
  98.                     return "RAID"
  99.  
  100.             if class_id == Pci.BASE_CLASS_COMMUNICATION \
  101.                and subclass_id == Pci.CLASS_COMMUNICATION_MODEM:
  102.                 return "MODEM"
  103.  
  104.             if class_id == Pci.BASE_CLASS_INPUT \
  105.                and subclass_id == Pci.CLASS_INPUT_SCANNER:
  106.                 return "SCANNER"
  107.  
  108.             if class_id == Pci.BASE_CLASS_MULTIMEDIA:
  109.                 if subclass_id == Pci.CLASS_MULTIMEDIA_VIDEO:
  110.                     return "CAPTURE"
  111.  
  112.                 if subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO \
  113.                    or subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO_DEVICE:
  114.                     return "AUDIO"
  115.  
  116.             if class_id == Pci.BASE_CLASS_SERIAL \
  117.                and subclass_id == Pci.CLASS_SERIAL_FIREWIRE:
  118.                 return "FIREWIRE"
  119.  
  120.             if class_id == Pci.BASE_CLASS_BRIDGE \
  121.                and (subclass_id == Pci.CLASS_BRIDGE_PCMCIA \
  122.                     or subclass_id == Pci.CLASS_BRIDGE_CARDBUS):
  123.                 return "SOCKET"
  124.  
  125.         if "bInterfaceClass" in self._attributes:
  126.             interface_class = int(self._attributes["bInterfaceClass"], 16)
  127.             interface_subclass = int(self._attributes["bInterfaceSubClass"], 16)
  128.  
  129.             if interface_class == Usb.BASE_CLASS_AUDIO:
  130.                 return "AUDIO"
  131.  
  132.             if interface_class == Usb.BASE_CLASS_PRINTER:
  133.                 return "PRINTER"
  134.  
  135.             if interface_class == Usb.BASE_CLASS_STORAGE:
  136.                 if interface_subclass == Usb.CLASS_STORAGE_FLOPPY:
  137.                     return "FLOPPY"
  138.  
  139.                 if interface_subclass == Usb.CLASS_STORAGE_SCSI:
  140.                     return "SCSI"
  141.  
  142.             if interface_class == Usb.BASE_CLASS_VIDEO:
  143.                 return "VIDEO"
  144.  
  145.             if interface_class == Usb.BASE_CLASS_WIRELESS:
  146.                 return "NETWORK"
  147.  
  148.         if "ID_TYPE" in self._environment:
  149.             id_type = self._environment["ID_TYPE"]
  150.  
  151.             if id_type == "cd":
  152.                 return "CDROM"
  153.  
  154.             if id_type == "disk":
  155.                 return "DISK"
  156.  
  157.             if id_type == "video":
  158.                 return "VIDEO"
  159.  
  160.         if "KEY" in self._environment:
  161.             key = self._environment["KEY"].strip("=")
  162.             bitmask = get_bitmask(key)
  163.  
  164.             for i in range(Input.KEY_Q, Input.KEY_P+1):
  165.                 if not test_bit(i, bitmask):
  166.                     break
  167.             else:
  168.                 return "KEYBOARD"
  169.  
  170.             if test_bit(Input.BTN_MOUSE, bitmask):
  171.                 return "MOUSE"
  172.  
  173.         if self._environment.get("DEVTYPE") == "disk":
  174.             if "ID_CDROM" in self._environment:
  175.                 return "CDROM"
  176.  
  177.             if "ID_DRIVE_FLOPPY" in self._environment:
  178.                 return "FLOPPY"
  179.  
  180.         if self._environment.get("DEVTYPE") == "scsi_device":
  181.             type = int(self._attributes.get("type", "-1"))
  182.             if type in (0, 7, 14):
  183.                 return "DISK"
  184.  
  185.             if type == 1:
  186.                 return "TAPE"
  187.  
  188.             if type == 2:
  189.                 return "PRINTER"
  190.  
  191.             if type in (4, 5):
  192.                 return "CDROM"
  193.  
  194.             if type == 6:
  195.                 return "SCANNER"
  196.  
  197.             if type == 12:
  198.                 return "RAID"
  199.  
  200.         if self._get_product_id():
  201.             return "OTHER"
  202.  
  203.         return None
  204.  
  205.     def _get_driver(self):
  206.         if "DRIVER" in self._environment:
  207.             return self._environment["DRIVER"]
  208.  
  209.         if "ID_USB_DRIVER" in self._environment:
  210.             return self._environment["ID_USB_DRIVER"]
  211.  
  212.         return None
  213.  
  214.     def _get_path(self):
  215.         return self._environment.get("DEVPATH")
  216.  
  217.     def _get_product_id(self):
  218.         # pci
  219.         if "PCI_ID" in self._environment:
  220.             vendor_id, product_id = self._environment["PCI_ID"].split(":")
  221.             return int(product_id, 16)
  222.  
  223.         # usb interface
  224.         if "PRODUCT" in self._environment \
  225.            and self._environment.get("DEVTYPE") == "usb_interface":
  226.             vendor_id, product_id, revision = self._environment["PRODUCT"].split("/")
  227.             return int(product_id, 16)
  228.  
  229.         # usb device and ieee1394
  230.         for attribute in "idProduct", "model_id":
  231.             if attribute in self._attributes:
  232.                 return int(self._attributes[attribute], 16)
  233.  
  234.         # pnp
  235.         if "id" in self._attributes:
  236.             match = re.match(r"^(?P<vendor_name>.*)(?P<product_id>[%s]{4})$"
  237.                 % string.hexdigits, self._attributes["id"])
  238.             if match:
  239.                 return int(match.group("product_id"), 16)
  240.  
  241.         return None
  242.  
  243.     def _get_vendor_id(self):
  244.         # pci
  245.         if "PCI_ID" in self._environment:
  246.             vendor_id, product_id = self._environment["PCI_ID"].split(":")
  247.             return int(vendor_id, 16)
  248.  
  249.         # usb interface
  250.         if "PRODUCT" in self._environment \
  251.            and self._environment.get("DEVTYPE") == "usb_interface":
  252.             vendor_id, product_id, revision = self._environment["PRODUCT"].split("/")
  253.             return int(vendor_id, 16)
  254.  
  255.         # usb device
  256.         if "idVendor" in self._attributes:
  257.             return int(self._attributes["idVendor"], 16)
  258.  
  259.         # ieee1394
  260.         vendor_id_path = posixpath.join(self._get_path(), "../vendor_id")
  261.         if posixpath.exists(vendor_id_path):
  262.             vendor_id = open(vendor_id_path, "r").read().strip()
  263.             return int(vendor_id, 16)
  264.  
  265.         return None
  266.  
  267.     def _get_subproduct_id(self):
  268.         if "PCI_SUBSYS_ID" in self._environment:
  269.             pci_subsys_id = self._environment["PCI_SUBSYS_ID"]
  270.             subvendor_id, subproduct_id = pci_subsys_id.split(":")
  271.             return int(subproduct_id, 16)
  272.  
  273.         return None
  274.  
  275.     def _get_subvendor_id(self):
  276.         if "PCI_SUBSYS_ID" in self._environment:
  277.             pci_subsys_id = self._environment["PCI_SUBSYS_ID"]
  278.             subvendor_id, subproduct_id = pci_subsys_id.split(":")
  279.             return int(subvendor_id, 16)
  280.  
  281.         return None
  282.  
  283.     def _get_product(self):
  284.         for element in ("NAME",
  285.                         "RFKILL_NAME",
  286.                         "POWER_SUPPLY_MODEL_NAME"):
  287.             if element in self._environment:
  288.                 return self._environment[element].strip('"')
  289.  
  290.         for attribute in ("description",
  291.                           "model_name_kv",
  292.                           "model",
  293.                           "product_name"):
  294.             if attribute in self._attributes:
  295.                 return self._attributes[attribute]
  296.  
  297.         # sound
  298.         bus = self._get_bus()
  299.         if bus == "sound":
  300.             device = posixpath.basename(self._environment["DEVPATH"])
  301.             match = re.match(r"(card|controlC|hwC|midiC)(?P<card>\d+)", device)
  302.             if match:
  303.                 card = match.group("card")
  304.                 in_card = False
  305.                 file = open("/proc/asound/cards", "r")
  306.                 for line in file.readlines():
  307.                     line = line.strip()
  308.                     match = re.match(r"(?P<card>\d+) \[", line)
  309.                     if match:
  310.                         in_card = match.group("card") == card
  311.  
  312.                     if in_card:
  313.                         match = re.match(r"""(?P<name>.*) """
  314.                             """at (?P<address>0x[%s]{8}) """
  315.                             """irq (?P<irq>\d+)""" % string.hexdigits, line)
  316.                         if match:
  317.                             return match.group("name")
  318.  
  319.             path = None
  320.             match = re.match(r"pcmC(?P<card>\d+)D(?P<device>\d+)(?P<type>\w)",
  321.                 device)
  322.             if match:
  323.                 path = "/proc/asound/card%s/pcm%s%c/info" % match.groups()
  324.  
  325.             match = re.match(r"(dsp|adsp|midi|amidi|audio|mixer)(?P<card>\d+)?",
  326.                 device)
  327.             if match:
  328.                 card = match.group("card") or 0
  329.                 path = "/proc/asound/card%s/pcm0p/info" % card
  330.  
  331.             if path and posixpath.exists(path):
  332.                 file = open(path, "r")
  333.                 for line in file.readlines():
  334.                     match = re.match(r"name: (?P<name>.*)", line)
  335.                     if match:
  336.                         return match.group("name")
  337.  
  338.         return None
  339.  
  340.     def _get_vendor(self):
  341.         if "RFKILL_NAME" in self._environment:
  342.             return None
  343.  
  344.         if "POWER_SUPPLY_MANUFACTURER" in self._environment:
  345.             return self._environment["POWER_SUPPLY_MANUFACTURER"]
  346.  
  347.         if "vendor" in self._attributes:
  348.             vendor = self._attributes["vendor"]
  349.             if not re.match(r"^0x[%s]{4}$" % string.hexdigits, vendor):
  350.                 return vendor
  351.  
  352.         # dmi
  353.         if "sys_vendor" in self._attributes:
  354.             return self._attributes["sys_vendor"]
  355.  
  356.         # pnp
  357.         if "id" in self._attributes:
  358.             match = re.match(r"^(?P<vendor_name>.*)(?P<product_id>[%s]{4})$"
  359.                 % string.hexdigits, self._attributes["id"])
  360.             if match:
  361.                 return match.group("vendor_name")
  362.  
  363.         # ieee1394
  364.         vendor_path = posixpath.join(self._get_path(), "../vendor_oui")
  365.         if posixpath.exists(vendor_path):
  366.             return open(vendor_path, "r").read().strip()
  367.  
  368.         return None
  369.  
  370.     def items(self):
  371.         return (
  372.             ("path", self._get_path()),
  373.             ("bus", self._get_bus()),
  374.             ("category", self._get_category()),
  375.             ("driver", self._get_driver()),
  376.             ("product_id", self._get_product_id()),
  377.             ("vendor_id", self._get_vendor_id()),
  378.             ("subproduct_id", self._get_subproduct_id()),
  379.             ("subvendor_id", self._get_subvendor_id()),
  380.             ("product", self._get_product()),
  381.             ("vendor", self._get_vendor()),
  382.             ("attributes", MapRegistry(self._attributes)),
  383.             ("environment", MapRegistry(self._environment)),
  384.             ("device", LinkRegistry(self)))
  385.  
  386.  
  387. class DmiDeviceRegistry(DeviceRegistry):
  388.  
  389.     def __init__(self, environment, attributes, category):
  390.         super(DmiDeviceRegistry, self).__init__(environment, attributes)
  391.         self._category = category
  392.  
  393.     def _get_category(self):
  394.         return self._category
  395.  
  396.     def _get_path(self):
  397.         path = super(DmiDeviceRegistry, self)._get_path()
  398.         return posixpath.join(path, self._category.lower())
  399.  
  400.     def _get_product(self):
  401.         if self._category == "CHASSIS":
  402.             type = int(self._attributes["chassis_type"])
  403.             return Dmi.chassis_names[type]
  404.  
  405.         for name in "name", "version":
  406.             attribute = "%s_%s" % (self._category.lower(), name)
  407.             product = self._attributes.get(attribute)
  408.             if product and product != "Not Available":
  409.                 return product
  410.  
  411.         return None
  412.  
  413.     @DmiNotAvailable
  414.     def _get_vendor(self):
  415.         attribute = "%s_vendor" % self._category.lower()
  416.         if attribute in self._attributes:
  417.             return self._attributes[attribute]
  418.  
  419.         return None
  420.  
  421.  
  422. class UdevRegistry(CommandRegistry):
  423.     """Registry for udev information."""
  424.  
  425.     # Command to retrieve udev information.
  426.     command = String(default="udevadm info --export-db")
  427.  
  428.     def _get_attributes(self, path):
  429.         attributes = {}
  430.         sys_path = "/sys%s" % path
  431.         try:
  432.             names = os.listdir(sys_path)
  433.         except OSError:
  434.             return attributes
  435.  
  436.         for name in names:
  437.             name_path = posixpath.join(sys_path, name)
  438.             if name[0] == "." \
  439.                or name in ["dev", "uevent"] \
  440.                or posixpath.isdir(name_path) \
  441.                or posixpath.islink(name_path):
  442.                 continue
  443.  
  444.             try:
  445.                 value = open(name_path, "r").read().strip()
  446.             except IOError:
  447.                 continue
  448.  
  449.             value = value.split("\n")[0]
  450.             if [c for c in value if not isprint(c)]:
  451.                 continue
  452.  
  453.             attributes[name] = value
  454.  
  455.         return attributes
  456.  
  457.     def _ignore_device(self, device):
  458.         # Ignore devices without bus information
  459.         if not device.bus:
  460.             return True
  461.  
  462.         # Ignore devices without product information
  463.         if not device.product and device.product_id is None:
  464.             return True
  465.  
  466.         # Ignore invalid subsystem information
  467.         if (device.subproduct_id is None and device.subvendor_id is not None) \
  468.            or (device.subproduct_id is not None and device.subvendor_id is None):
  469.             return True
  470.  
  471.         # Ignore virtual devices except for dmi information
  472.         if device.bus != "dmi" \
  473.            and "virtual" in device.path.split(posixpath.sep):
  474.             return True
  475.  
  476.         return False
  477.  
  478.     @cache
  479.     def items(self):
  480.         devices = []
  481.         line_pattern = re.compile(r"(?P<key>\w):\s*(?P<value>.*)")
  482.         multi_pattern = re.compile(r"(?P<key>\w+)=(?P<value>.*)")
  483.  
  484.         for record in str(self).split("\n\n"):
  485.             if not record:
  486.                 continue
  487.  
  488.             # Determine path and environment
  489.             path = None
  490.             environment = {}
  491.             for line in record.split("\n"):
  492.                 match = line_pattern.match(line)
  493.                 if not match:
  494.                     raise Exception, \
  495.                         "Device line not supported: %s" % line
  496.  
  497.                 key = match.group("key")
  498.                 value = match.group("value")
  499.  
  500.                 if key == "P":
  501.                     path= value
  502.                 elif key == "E":
  503.                     match = multi_pattern.match(value)
  504.                     if not match:
  505.                         raise Exception, \
  506.                             "Device property not supported: %s" % value
  507.                     environment[match.group("key")] = match.group("value")
  508.  
  509.             # Set default DEVPATH
  510.             environment.setdefault("DEVPATH", path)
  511.  
  512.             # Determine attributes
  513.             attributes = self._get_attributes(path)
  514.  
  515.             if path == "/devices/virtual/dmi/id":
  516.                 device = DeviceRegistry(environment, attributes)
  517.                 devices.append(device)
  518.                 for category in "BIOS", "BOARD", "CHASSIS":
  519.                     device = DmiDeviceRegistry(environment, attributes, category)
  520.                     devices.append(device)
  521.             else:
  522.                 device = DeviceRegistry(environment, attributes)
  523.                 devices.append(device)
  524.  
  525.         return [(d.path, d) for d in devices if not self._ignore_device(d)]
  526.  
  527.  
  528. factory = UdevRegistry
  529.